﻿using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;

public class MaterialTools
{
    public const string TYPE_3D_PATH = "Assets/Resources/OutPut/";
    public static string ShaderUsedTxtPath = "/Editor/Template/ShaderUsed.txt";
    public static string ColorShaderName = "Unlit/Transparent Colored";
    static Dictionary<string, List<string>> shaderUsed = new Dictionary<string, List<string>>();

    [MenuItem("GameEditor/打印材质使用的shader", false, 40)]
    public static void DispAllShaderUsed()
    {
        shaderUsed.Clear();
        Object[] objs = Selection.GetFiltered(typeof(Material), SelectionMode.DeepAssets);

        for (int i = 0; i < objs.Length; i++)
        {
            Material mat = objs[i] as Material;
            EditorUtility.DisplayProgressBar("正在转换", mat.name, (i + 1f) / objs.Length);
            string shaderName = mat.shader.name;
            if (!shaderUsed.ContainsKey(shaderName))
            {
                shaderUsed[shaderName] = new List<string>();
            }
            if (!shaderUsed[shaderName].Contains(mat.name))
            {
                shaderUsed[shaderName].Add(mat.name);
            }
        }

        StringBuilder sb = new StringBuilder();
        foreach (var p in shaderUsed)
        {
            string shaderName = p.Key;
            List<string> mats = p.Value;
            sb.Append(string.Format("ShaderName:{0}\n", shaderName));
            for (int idx = 0; idx < mats.Count; ++idx)
            {
                sb.Append(string.Format("\t\t\t{0}\n", mats[idx]));
            }
        }

        string fullPath = Application.dataPath + ShaderUsedTxtPath;
        StreamWriter writer = new StreamWriter(fullPath, false, Encoding.UTF8);
        writer.Write(sb.ToString()); writer.Close();
        EditorUtility.ClearProgressBar();
    }
    
    [MenuItem("GameEditor/材质贴图转换", false, 40)]
    public static void SetTexture()
    {
        Object[] objs = Selection.GetFiltered(typeof(Material), SelectionMode.DeepAssets);

        for (int i = 0; i < objs.Length; i++)
        {
            Material mat = objs[i] as Material;
            EditorUtility.DisplayProgressBar("正在转换", mat.name, (i + 1f) / objs.Length);
            if (mat.shader.name == ColorShaderName)
            {
                Texture tex = mat.GetTexture("_MainTex");
                if (tex != null)
                {
                    string path = AssetDatabase.GetAssetPath(tex);
                    path = path.Replace("Atlas/OutPut", "Atlas");
                    string rgbPath = path.Replace(".png", "_RGB.png");
                    string aPath = path.Replace(".png", "_A.png");

                    tex = AssetDatabase.LoadAssetAtPath<Texture>(rgbPath);
                    if (tex != null)
                    {
                        mat.SetTexture("_MainTex", tex);
                        tex = AssetDatabase.LoadAssetAtPath<Texture>(aPath);
                        mat.SetTexture("_AlphaTex", tex);
                    }
                }
            }
        }
        AssetDatabase.Refresh();
        EditorUtility.ClearProgressBar();
    }

    [MenuItem("GameEditor/材质还原转换", false, 40)]
    public static void UnSetTexture()
    {
        Object[] objs = Selection.GetFiltered(typeof(Material), SelectionMode.DeepAssets);

        for (int i = 0; i < objs.Length; i++)
        {
            Material mat = objs[i] as Material;
            EditorUtility.DisplayProgressBar("正在转换", mat.name, (i + 1f) / objs.Length);
            if (mat.shader.name == ColorShaderName)
            {
                Texture tex = mat.GetTexture("_MainTex");
                if (tex != null)
                {
                    string rgbPath = AssetDatabase.GetAssetPath(tex);
                    rgbPath = rgbPath.Replace("Atlas/OutPut", "Atlas");
                    string path = rgbPath.Replace("_RGB.png", ".png");

                    tex = AssetDatabase.LoadAssetAtPath<Texture>(path);
                    if (tex != null) { mat.SetTexture("_MainTex", tex); }
                }
            }
        }
        AssetDatabase.Refresh();
        EditorUtility.ClearProgressBar();
    }

    [MenuItem("GameEditor/3D材质拆图", false, 40)]
    public static void DivideTexture()
    {
        Object[] objs = Selection.GetFiltered(typeof(Material), SelectionMode.DeepAssets);
        Debug.Log(string.Format("开始拆分透明通道，一共需要处理{0}个材质", objs.Length));

        for (int i = 0; i < objs.Length; i++)
        {
            Material mat = objs[i] as Material;
            //EditorUtility.DisplayProgressBar("正在转换", mat.name, (i + 1f) / objs.Length);
            switch (mat.shader.name)
            {
                case "Custom/DSParticleBlend":
                    ChangeShader(mat, "Hidden/DSParticleBlend_Alpha");
                    break;
                case "Mobile/Particles/Additive":
                    ChangeShader(mat, "Hidden/Mobile/Particles/Additive");
                    break;
                case "Custom/Mobile_AlphaBlend":
                    ChangeShader(mat, "Hidden/Mobile_AlphaBlend_Alpha");
                    break;
                case "Mobile/Particles/Alpha Blended":
                    ChangeShader(mat, "Hidden/Mobile/Particles/Alpha Blended");
                    break;
                case "Custom/DSParticleAdditive":
                    ChangeShader(mat, "Hidden/DSParticleAdditive_Alpha");
                    break;
                case "Custom/SimpleReflection":
                    ChangeShader(mat, "Hidden/SimpleReflection_Alpha");
                    break;
                case "Custom/Additive_Flip":
                    ChangeShader(mat, "Hidden/Additive_Flip_Alpha");
                    break;
                case "Custom/Additive_We":
                    ChangeShader(mat, "Hidden/Additive_We_Alpha");
                    break;
                case "Custom/SimpleAlpha":
                    ChangeShader(mat, "Hidden/SimpleAlpha_Alpha");
                    break;
                case "Custom/Mobile_Additive":
                    ChangeShader(mat, "Hidden/Mobile_Additive_Alpha");
                    break;
                case "Transparent/Diffuse":
                    ChangeShader(mat, "Custom/Transparent/Diffuse");
                    break;
                case "Custom/ShineViewWithSky":
                    ChangeShader(mat, "Hidden/ShineViewWithSky_Alpha");
                    break;
                case "Custom/DoubleDiffuse":
                    ChangeShader(mat, "Hidden/DoubleDiffuse_Alpha");
                    break;
                case "Custom/3D Text Shader":
                    ChangeShader(mat, "Hidden/3D Text Shader_Alpha");
                    break;
                case "Diffuse Detail":
                    ChangeShader(mat, "Custom/Diffuse Detail");
                    break;
                case "Custom/UVAnim":
                    ChangeShader(mat, "Hidden/UVAnim_Alpha");
                    break;
                case "Sprites/Diffuse":
                    ChangeShader(mat, "Custom/Sprites/Diffuse");
                    break;
            }
        }
        AssetDatabase.Refresh();
        //EditorUtility.ClearProgressBar();
    }

    static void ChangeShader(Material mat, string shaderName, string mainName = "_MainTex")
    {
        Texture tex = mat.GetTexture(mainName);
        if (tex == null) { return; }
        string path = AssetDatabase.GetAssetPath(tex);
        TextureImporter srcImp = AssetImporter.GetAtPath(path) as TextureImporter;

        int androidSize = 0; TextureImporterFormat androidFormat;
        if (srcImp == null)
        {
            Debug.Log(string.Format("SrcImp is NULL matName {0} path:{1}", mat.name, path));
            return;
        }
        srcImp.GetPlatformTextureSettings(BuildTarget.Android.ToString(), out androidSize, out androidFormat);
        if (androidFormat == TextureImporterFormat.ETC_RGB4
            || androidFormat == TextureImporterFormat.AutomaticCompressed)
        {
            return;
        }

        if (srcImp.grayscaleToAlpha)
        {
            Debug.LogError("Use Alpha from Grayscale");
            return;
        }
        Shader sh = Shader.Find(shaderName);
        if (sh != null)
        {
            mat.shader = sh;
            HandleDivide(mat);
        }
        else
        {
            Debug.Log(string.Format("ChangeShader未能找到Shader:{0}", shaderName));
        }
    }

    static void CopyTexParam(TextureImporter src, TextureImporter des)
    {
        //Debug.Log(string.Format("Begin Copy Tex Param {0} {1}", src.assetPath, des.assetPath));
        des.textureType = src.textureType;
        des.npotScale = src.npotScale;
        des.isReadable = src.isReadable;
        des.mipmapEnabled = src.mipmapEnabled;
        des.textureFormat = src.textureFormat;
        des.anisoLevel = src.anisoLevel;
        des.alphaIsTransparency = src.alphaIsTransparency;
        des.grayscaleToAlpha = src.grayscaleToAlpha;
        des.wrapMode = src.wrapMode;

        int androidSize = 0; int iosSize = 0;
        TextureImporterFormat androidFormat;
        TextureImporterFormat iosFormat;

        src.GetPlatformTextureSettings(BuildTarget.Android.ToString(), out androidSize, out androidFormat);
        src.GetPlatformTextureSettings(BuildTarget.iOS.ToString(), out iosSize, out iosFormat);
        des.SetPlatformTextureSettings(BuildTarget.Android.ToString(), androidSize, TextureImporterFormat.ETC_RGB4);
        des.SetPlatformTextureSettings(BuildTarget.iOS.ToString(), iosSize, iosFormat);
        AssetDatabase.ImportAsset(des.assetPath);
    }

    static void HandleDivide(Material mat, string mainName = "_MainTex", string alphaName = "_AlphaTex")
    {
        Debug.Log(string.Format("Handle Divede {0}", mat.name));
        Texture tex = mat.GetTexture(mainName);
        if (tex != null)
        {
            string path = AssetDatabase.GetAssetPath(tex);
            TextureImporter srcImp = AssetImporter.GetAtPath(path) as TextureImporter;
            int idx = path.LastIndexOf('/');
            string texName = path.Substring(idx + 1, path.Length - idx - 1);
            string newPath = TYPE_3D_PATH + texName;
            int dotIdx = newPath.LastIndexOf('.');
            if (dotIdx > 0)
            {
                string rgbPath = newPath.Insert(dotIdx, "_RGB");
                string aPath = newPath.Insert(dotIdx, "_A");
                tex = AssetDatabase.LoadAssetAtPath<Texture>(rgbPath);
                TextureImporter rgbImp = AssetImporter.GetAtPath(rgbPath) as TextureImporter;
                if (tex != null)
                {
                    CopyTexParam(srcImp, rgbImp);
                    mat.SetTexture(mainName, tex);
                    tex = AssetDatabase.LoadAssetAtPath<Texture>(aPath);
                    TextureImporter aImp = AssetImporter.GetAtPath(aPath) as TextureImporter;
                    CopyTexParam(srcImp, aImp);
                    mat.SetTexture(alphaName, tex);
                }
                else { Debug.LogWarning(string.Format("找不到材质主贴图：{0}", rgbPath)); }
            }
        }
        else
        {
            Debug.LogWarning(string.Format("无法处理材质：{0}", mat.ToString()));
        }
    }
}